﻿//#define Debug

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DD.DDMudLibrary
{
    public class DDMudCommandProcessor
    {
        public delegate void SetTimerDelegate(int Ms);
        SetTimerDelegate SetTimer;

        public delegate void ShowClientMsgDelegate(string Str);
        ShowClientMsgDelegate ShowClientMsg;

        private enum ComStat
        {
            Begin,
            Normal,
            PathFound,
            PoundFound,
            End,
        }

        private ComStat CStat;

        private List<string> CommandList = new List<string>();
        private delegate void CommandDelegate(List<string> Args);
        private List<CommandDelegate> RunCommand = new List<CommandDelegate>();

        public DDMudCommandProcessor()
        {
            CStat = ComStat.Begin;
            
            // CommandList.Add("action");
            // RunCommand.Add(   );
            // CommandList.Add("alias");
            // RunCommand.Add(   );
            // CommandList.Add("showme");
            // RunCommand.Add(   );
            // CommandList.Add("tick");
            // RunCommand.Add(   );
        }

        public DDMudCommandProcessor(SetTimerDelegate SetTimerFunc, ShowClientMsgDelegate ShowClientMsgFunc)
            : this()
        {
            SetTimer = SetTimerFunc;
            ShowClientMsg = ShowClientMsgFunc;
        }

        public string ProcessOneCommand(string Command)
        {
            int i, j, k;
            string RealCommand = "";
            int PathTimes;

            CStat = ComStat.Begin;
            i = 0;
            Command = Command.TrimStart(' ');
            while(i < Command.Length && CStat != ComStat.End)
            {
                if (CStat == ComStat.Begin)
                {
                    // Path?
                    for (j = i; j < Command.Length && char.IsNumber(Command, j); j++) ;
                    if (Command.Length > j &&
                        (Command[j] == 'u' ||
                        Command[j] == 'd' ||
                        Command[j] == 'w' ||
                        Command[j] == 'e' ||
                        Command[j] == 'n' ||
                        Command[j] == 's'))
                    {
                        if (j > i)
                        {
                            PathTimes = Convert.ToInt32(Command.Substring(i, j - i));
                        }
                        else
                        {
                            PathTimes = 1;
                        }

                        for (k = 0; k < PathTimes; k++)
                        {
                            RealCommand += Command[j] + "\r\n";
                        }
                        i = j + 1;
                        CStat = ComStat.PathFound;
                    }
                    else if (Command[0] == '#')
                    {
                        CStat = ComStat.PoundFound;
                        i++;
                    }
                    else
                    {
                        // Normal
                        CStat = ComStat.Normal;
                        i = 0;
                    }
                }
                else if (CStat == ComStat.Normal)
                {

                    // alias process

                    RealCommand = Command + "\r\n";
                    CStat = ComStat.End;
                }
                else if (CStat == ComStat.PathFound)
                {
                    // Start with a Path
                    for (j = i; j < Command.Length && char.IsNumber(Command, j); j++) ;
                    if (Command.Length > j &&
                        (Command[j] == 'u' ||
                        Command[j] == 'd' ||
                        Command[j] == 'w' ||
                        Command[j] == 'e' ||
                        Command[j] == 'n' ||
                        Command[j] == 's'))
                    {
                        if (j > i)
                        {
                            PathTimes = Convert.ToInt32(Command.Substring(i, j - i));
                        }
                        else
                        {
                            PathTimes = 1;
                        }

                        for (k = 0; k < PathTimes; k++)
                        {
                            RealCommand += Command[j] + "\r\n";
                        }
                        i = j + 1;
                        CStat = ComStat.PathFound;
                    }
                    else
                    {
                        // Start with a path but not a fully path
                        CStat = ComStat.Normal;
                        i = 0;
                    }
                }
                else if (CStat == ComStat.PoundFound)
                {
                    // Control Commands
                    List<string> CommandBlocks = GetCommandBlocks(Command.Substring(1));
                    string ControlCommand = CommandBlocks[0].ToLower();
                    int FoundCounter = 0;
                    int CommandNo = -1;

                    for (j = 0; j < CommandList.Count(); j++)
                    {
                        if (CommandList[j].IndexOf(ControlCommand) == 0)
                        {
                            FoundCounter++;
                            CommandNo = j;
                        }
                    }

                    if (FoundCounter == 0)
                    {
                        ShowClientMsg("Command #" + CommandBlocks[0] + " does not exist!\n");
                    }
                    else
                    {
                        CommandBlocks[0] = CommandList[CommandNo];
#if Debug
                        ShowClientMsg("Command #" + CommandBlocks[0] + " with args:\n");
                        for (j = 1; j < CommandBlocks.Count(); j++)
                        {
                            ShowClientMsg(CommandBlocks[j] + "\n");
                        }
#endif
                        RunCommand[CommandNo](CommandBlocks);
                    }

                    RealCommand = "";
                    CStat = ComStat.End;
                }
                else
                {
                    // unknown
                }
            }
            if (Command.Length == 0)
            {
                RealCommand = "\r\n";
            }

            return (RealCommand);
        }

        private List<string> GetCommandBlocks(string InputString)
        {
            List<string> StringList = new List<string>();
            int TempPos;

            InputString = InputString.Trim();
            while (InputString.Count() > 0)
            {
                if(InputString[0] == '{')
                {
                    TempPos = InputString.IndexOf('}');
                    if (TempPos != -1)
                    {
                        StringList.Add(InputString.Substring(1, TempPos - 1));
                        InputString = InputString.Substring(TempPos + 1);
                    }
                    else
                    {
                        StringList.Add(InputString);
                        InputString = "";
                    }
                }
                else
                {
                    TempPos = InputString.IndexOf(' ');
                    if (TempPos != -1)
                    {
                        StringList.Add(InputString.Substring(0, TempPos));
                        InputString = InputString.Substring(TempPos + 1);
                    }
                    else
                    {
                        StringList.Add(InputString);
                        InputString = "";
                    }
                }
                InputString = InputString.Trim();
            }

            return (StringList);
        }
    }
}
